package crontab

import (
	"encoding/json"
	"fmt"
	"github.com/spf13/cast"
	"github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common"
	"github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common/profile"
	vod "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/vod/v20180717"
	global2 "longmen/server/config/global"
	"longmen/server/pkg/db/mysql/models/models_live"
	"longmen/server/pkg/db/mysql/models/models_main"
	"longmen/server/pkg/db/redis/cache"
	"strings"
	"time"
)

// 同步直播录制回放, 更新回调缺失的数据
func SyncLiveRecordReply() {
	configPri := cache.GetConfigPri()
	cred := common.NewCredential(configPri.QcloudLiveSecretid, configPri.QcloudLiveSecretkey)
	credential := common.NewCredential(
		cred.SecretId,
		cred.SecretKey,
	)
	cpf := profile.NewClientProfile()
	c, _ := vod.NewClient(credential, "", cpf)
	doLiveRecordReplySync(c, configPri.QcloudLiveAppid)
}

func doLiveRecordReplySync(c *vod.Client, subAppId string) {
	//查询参数, 五天内的不包含回放的直播记录
	stTime := time.Now().AddDate(0, 0, -5)
	offset, limit := uint64(0), uint64(1000)

	//查询系统中没有回放的直播的streamId
	streamIds, liveHisMp := getLiveWithoutReplyStreamIds(stTime.Unix(), int(limit))

	//装配参数
	req := vod.NewSearchMediaRequest()
	req.SubAppId = common.Uint64Ptr(cast.ToUint64(subAppId))
	req.Offset = &offset
	req.Limit = &limit
	req.StreamIds = streamIds

	//查询
	var videos []*models_live.Video
	for i := 0; i < len(streamIds); i += 9 {
		if i+9 > len(streamIds) {
			req.StreamIds = streamIds[i:len(streamIds)]
		} else {
			req.StreamIds = streamIds[i : i+9]
		}
		resp, err := c.SearchMedia(req)
		if err != nil {
			global2.Log.Errorf("Search media failed, err:%v", err)
			continue
		}

		if resp.Response != nil && resp.Response.TotalCount != nil && *resp.Response.TotalCount > 0 {
			for _, info := range resp.Response.MediaInfoSet {
				if info == nil || info.BasicInfo == nil {
					continue
				}
				basicInfo := info.BasicInfo
				basicInfoStr, _ := json.Marshal(basicInfo)
				// 计算时长
				hour := int(*info.MetaData.Duration) / 3600
				min := (int(*info.MetaData.Duration) % 3600) / 60
				sec := (int(*info.MetaData.Duration) % 3600) % 60

				callback := strings.Split(*basicInfo.Name, "_")
				if len(callback) < 2 {
					global2.Log.Errorf("Split basicInfo.Name %v failed, err:%v", basicInfo, err)
					continue
				}
				stream := callback[0] + "_" + callback[1]
				liveHis, ok := liveHisMp[stream]
				if !ok {
					global2.Log.Errorf("liveHisMp %v failed, err:%v", liveHisMp, err)
					continue
				}

				video := &models_live.Video{
					AnchorID:    liveHis.Anchorid,
					PlayURL:     *basicInfo.MediaUrl,
					Title:       liveHis.Title,
					Type:        models_main.LiveRecordType, //录制回放
					CallbackReq: string(basicInfoStr),
					TCFileID:    *info.FileId,
					Stream:      stream,
					Duration:    fmt.Sprintf("%d:%d:%d", hour, min, sec),
					CreateTime:  time.Now().Unix(),
				}
				videos = append(videos, video)
			}
		}
		time.Sleep(time.Millisecond * 50)
	}
	if len(videos) > 0 {
		err := global2.GetX().Create(&videos).Error
		if err != nil {
			global2.Log.Errorf("Record2Video %v failed, err:%v", videos, err)
		}
	}
}

func getLiveWithoutReplyStreamIds(stTimestamp int64, limit int) (noSyncedStreamIds []*string, noSyncedLiveHisMp map[string]models_live.LiveHistory) {
	noSyncedStreamIds = []*string{}
	noSyncedLiveHisMp = map[string]models_live.LiveHistory{}

	var liveHis []*models_live.LiveHistory
	liveHisMp := map[string]models_live.LiveHistory{}
	var streamIds []*string
	err := global2.Live().Model(&models_live.LiveHistory{}).Where("start_stamp > ? and status = ? and categoryid != ?", stTimestamp, 5, 112).Limit(limit).Select("stream, title, anchorid").Find(&liveHis).Error
	if err != nil {
		global2.Log.Errorf("Get live history failed, err:%v", err)
		return
	}
	for i, history := range liveHis {
		streamIds = append(streamIds, &history.Stream)
		liveHisMp[history.Stream] = *liveHis[i]
	}

	var syncedStreamIds []*string
	err = global2.GetR().Model(&models_main.Video{}).Where("stream in ?", streamIds).Select("stream").Find(&syncedStreamIds).Error
	if err != nil {
		global2.Log.Errorf("Get live Video failed, err:%v", err)
		return
	}
	syncStreamMp := map[string]int{}
	for _, id := range syncedStreamIds {
		syncStreamMp[*id] = 1
	}

	for _, id := range streamIds {
		_, ok := syncStreamMp[*id]
		if !ok {
			streamId := *id
			noSyncedStreamIds = append(noSyncedStreamIds, &streamId)
			noSyncedLiveHis, ok2 := liveHisMp[streamId]
			if ok2 {
				noSyncedLiveHisMp[streamId] = noSyncedLiveHis
			}
		}
	}
	return
}
